package com.cloud.sso.common.log.aop;


import com.cloud.sso.common.log.LogManager;
import com.cloud.sso.common.log.annoatation.BusinessLog;
import com.cloud.sso.common.log.factory.LogTaskFactory;
import com.cloud.sso.common.util.IpUtils;
import com.cloud.sso.oauth.obj.AppUserDetails;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;

/**
 * Created by tyd on 2017-10-13.
 *
 * @author tyd
 */
/*@Component
@Aspect*/
public class BusinessLogAop {

    private static final Logger logger = LoggerFactory.getLogger(BusinessLogAop.class);

    @Autowired
    private LogTaskFactory logTaskFactory;

    @Pointcut(value = "execution(* com.cloud.*.web.*.*(..))")
    public void cutService() {
    }

    @Around(value = "cutService()")
    public Object service(ProceedingJoinPoint point) throws Throwable {

        Object result = point.proceed();

        try {
            handle(point);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


    private void handle(ProceedingJoinPoint point) throws NoSuchMethodException {

        MethodSignature methodSignature = (MethodSignature) point.getSignature();

        Method method = point.getTarget().getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes());

        BusinessLog businessLog = method.getAnnotation(BusinessLog.class);

        /* Authentication authentication = SecurityContextHolder.getContext().getAuthentication();*/
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpSession httpSession = (HttpSession) requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
        SecurityContext securityContext = (SecurityContext) httpSession.getAttribute("SPRING_SECURITY_CONTEXT");

        Authentication authentication = securityContext.getAuthentication();

        if (businessLog != null
                && authentication != null
                && authentication.getPrincipal() instanceof AppUserDetails) {
            logger.info("日志操作：" + businessLog.value());

            AppUserDetails appUserDetails = (AppUserDetails) authentication.getPrincipal();


            String bId = null;
            // 记录方法参数
            Object[] args = point.getArgs();
            for (Object arg : args) {
                if (arg instanceof String && arg != null) {
                    bId = (String) arg;
                }
            }

            LogManager.getLogManager().executeLog(logTaskFactory.log(businessLog.value(),
                    businessLog.module(),
                    appUserDetails.getRealName(),
                    businessLog.type(),
                    bId,
                    getIP(),
                    getURI()));
        }

    }

    private static String getIP() {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = attributes.getRequest();

        String ip = request.getHeader("x-forwarded-for");

        if (!IpUtils.checkIP(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (!IpUtils.checkIP(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (!IpUtils.checkIP(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    public static String getURI() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = attributes.getRequest();
        return request.getRequestURI();
    }

}
